package com.haohan.cloud.scm.manage.core.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.haohan.cloud.scm.api.constant.ScmCacheNameConstant;
import com.haohan.cloud.scm.api.constant.ScmCommonConstant;
import com.haohan.cloud.scm.api.constant.enums.manage.MerchantPdsTypeEnum;
import com.haohan.cloud.scm.api.constant.enums.manage.MerchantStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.manage.ShopLevelEnum;
import com.haohan.cloud.scm.api.constant.enums.opc.YesNoEnum;
import com.haohan.cloud.scm.api.manage.entity.Merchant;
import com.haohan.cloud.scm.api.manage.entity.Shop;
import com.haohan.cloud.scm.api.manage.req.MerchantFeignReq;
import com.haohan.cloud.scm.api.manage.req.merchant.QueryMerchantReq;
import com.haohan.cloud.scm.api.manage.vo.MerchantVO;
import com.haohan.cloud.scm.common.tools.exception.ErrorDataException;
import com.haohan.cloud.scm.common.tools.thread.ScmGlobalThreadPool;
import com.haohan.cloud.scm.common.tools.util.ScmIncrementUtil;
import com.haohan.cloud.scm.manage.core.MerchantCoreService;
import com.haohan.cloud.scm.manage.service.MerchantService;
import com.haohan.cloud.scm.manage.service.ShopService;
import com.haohan.cloud.scm.manage.utils.ScmManageUtils;
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author dy
 * @date 2020/3/3
 */
@Service
@AllArgsConstructor
public class MerchantCoreServiceImpl implements MerchantCoreService {

    private final MerchantService merchantService;
    private final ShopService shopService;
    private final ScmManageUtils scmManageUtils;
    private final ScmIncrementUtil scmIncrementUtil;

    @Override
    public IPage<MerchantVO> findPage(Page<Merchant> page, QueryMerchantReq req) {
        IPage<Merchant> merchantPage = merchantService.page(page, Wrappers.query(req.tranTo()).lambda()
                .like(StrUtil.isNotEmpty(req.getMerchantName()), Merchant::getMerchantName, req.getMerchantName())
                .like(StrUtil.isNotEmpty(req.getAddress()), Merchant::getAddress, req.getAddress())
                .like(StrUtil.isNotEmpty(req.getContact()), Merchant::getContact, req.getContact())
                .like(StrUtil.isNotEmpty(req.getTelephone()), Merchant::getTelephone, req.getTelephone())
                .like(StrUtil.isNotEmpty(req.getIndustry()), Merchant::getIndustry, req.getIndustry())
                // 按商家类型 顺序(普通商家排在前)
                .orderByAsc(Merchant::getPdsType)
                .orderByDesc(Merchant::getCreateDate)
        );
        IPage<MerchantVO> result = new Page<>(merchantPage.getCurrent(), merchantPage.getSize(), merchantPage.getTotal());
        result.setRecords(merchantPage.getRecords().stream().map(MerchantVO::new)
                .collect(Collectors.toList())
        );
        return result;
    }

    @Override
    @Cacheable(value = ScmCacheNameConstant.MANAGE_MERCHANT_INFO, key = "#merchantId")
    public MerchantVO fetchInfo(String merchantId) {
        Merchant merchant = merchantService.getById(merchantId);
        if (null == merchant) {
            throw new ErrorDataException("商家有误");
        }
        return new MerchantVO(merchant);
    }

    @Override
    public MerchantVO fetchPlatform() {
        Merchant merchant = merchantService.fetchPlatformMerchant();
        if (null == merchant) {
            throw new ErrorDataException("平台商家有误");
        }
        return new MerchantVO(merchant);
    }

    /**
     * 创建平台的商家
     *
     * @param merchant
     * @return
     */
    @Override
    public Merchant createMerchantWithPlatform(Merchant merchant) {
        Merchant pmMerchant = merchantService.fetchPlatformMerchant();
        merchant.setParentId(pmMerchant.getId());
        merchantService.save(merchant);
        return merchant;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MerchantVO initPlatform(Merchant merchant) {
        Merchant exist = merchantService.fetchPlatformMerchant();
        if (null != exist) {
            throw new ErrorDataException("已存在平台商家");
        }
        merchant.setStatus(MerchantStatusEnum.enabled);
        merchant.setIsAutomaticOrder(YesNoEnum.no);
        merchant.setPdsType(MerchantPdsTypeEnum.platform);
        merchant.setParentId("0");
        merchantService.save(merchant);
        // 初始化商家店铺
        Shop shop = new Shop();
        shop.setName(merchant.getMerchantName() + "的店铺");
        shop.setAddress(merchant.getAddress());
        shop.setManager(merchant.getContact());
        shop.setTelephone(merchant.getTelephone());
        shop.setMerchantId(merchant.getId());
        shop.setStatus(MerchantStatusEnum.enabled);
        shop.setShopLevel(ShopLevelEnum.pds);
        shop.setIndustry(merchant.getIndustry());
        shopService.save(shop);

        // 创建 商家id:租户id 存入缓存 (原系统使用)
        Map<String, String> map = new HashMap<>(4);
        map.put(merchant.getId(), TenantContextHolder.getTenantId().toString());
        scmIncrementUtil.mapPut(ScmCommonConstant.TENANT_MAP_KEY, map);
        // 刷新平台商家缓存
        merchantService.flushPlatformMerchant();
        return new MerchantVO(merchant);
    }

    @Override
    public boolean addMerchant(Merchant merchant) {
        checkMerchantType(merchant);
        if (merchant.getPdsType() == null) {
            merchant.setPdsType(MerchantPdsTypeEnum.general);
        }
        // 兼容原系统的属性
        merchant.setIsAutomaticOrder(YesNoEnum.no);
        Merchant pmMerchant = merchantService.fetchPlatformMerchant();
        merchant.setParentId(pmMerchant.getId());
        return merchantService.save(merchant);
    }

    /**
     * 商家 不可新增、修改为平台商家
     *
     * @param merchant
     */
    private void checkMerchantType(Merchant merchant) {
        if (merchant.getPdsType() == MerchantPdsTypeEnum.platform) {
            merchant.setPdsType(null);
        }
    }

    @Override
    public boolean modifyMerchant(Merchant merchant) {
        Merchant exist = merchantService.getById(merchant.getId());
        if (null == exist) {
            throw new ErrorDataException("商家有误");
        }
        checkMerchantType(merchant);
        if (StrUtil.isNotEmpty(merchant.getMerchantName()) && !StrUtil.equals(merchant.getMerchantName(), exist.getMerchantName())) {
            // 名称修改同时更新关联表
            modifyRelationMerchantName(merchant.getId(), merchant.getMerchantName());
        }
        if (exist.getPdsType() == MerchantPdsTypeEnum.platform) {
            merchantService.flushPlatformMerchant();
        }
        return merchantService.updateById(merchant);
    }

    /**
     * 名称修改同时更新关联表
     *
     * @param merchantId
     * @param merchantName
     */
    private void modifyRelationMerchantName(String merchantId, String merchantName) {
        ScmGlobalThreadPool.getExecutor().execute(() -> {
            // supplier buyer
            scmManageUtils.updateSupplierMerchant(merchantId, merchantName);
            scmManageUtils.updateBuyerMerchant(merchantId, merchantName);
            // bill   账单 pmName merchantName  结算单 pmName companyName
            scmManageUtils.updateBillMerchant(merchantId, merchantName);
            // shipRecord  pmName
            scmManageUtils.updateShipRecordMerchant(merchantId, merchantName);
        });
        ScmGlobalThreadPool.getExecutor().execute(() -> {
            // crm下相关商家名称
            // customer  customerMerchantRelation
            // salesOrder
            // dataReport
            scmManageUtils.updateCustomerMerchant(merchantId, merchantName);
        });
    }

    @Override
    @CacheEvict(value = ScmCacheNameConstant.MANAGE_MERCHANT_INFO, key = "#merchantId")
    public boolean deleteMerchant(String merchantId) {
        Merchant merchant = merchantService.getById(merchantId);
        if (null == merchant) {
            throw new ErrorDataException("商家有误");
        }
        if (merchant.getPdsType() == MerchantPdsTypeEnum.platform) {
            throw new ErrorDataException("平台商家不可删除");
        }
        checkMerchantRelation(merchantId);
        return merchantService.removeById(merchantId);
    }

    /**
     * 检查是否有关联商家的数据
     *
     * @param merchantId
     */
    private void checkMerchantRelation(String merchantId) {
        int shopNum = shopService.count(Wrappers.<Shop>query().lambda()
                .eq(Shop::getMerchantId, merchantId)
        );
        if (shopNum > 0) {
            throw new ErrorDataException("商家下有店铺, 不可删除");
        }
        int customerNum = scmManageUtils.countCustomerNum(merchantId);
        if (customerNum > 0) {
            throw new ErrorDataException("商家下有对应客户, 不可删除");
        }
        int buyerNum = scmManageUtils.countBuyerNum(merchantId);
        if (buyerNum > 0) {
            throw new ErrorDataException("商家下有采购人员, 不可删除");
        }
        int supplierNum = scmManageUtils.countSupplierNum(merchantId);
        if (supplierNum > 0) {
            throw new ErrorDataException("商家下有供应人员, 不可删除");
        }
    }

    /**
     * 根据merchantId 集合和 启用状态 查询列表
     *
     * @param req
     * @return
     */
    @Override
    public List<MerchantVO> findMerchantList(MerchantFeignReq req) {
        return merchantService.list(Wrappers.<Merchant>query().lambda()
                .in(CollUtil.isNotEmpty(req.getMerchantIdSet()), Merchant::getId, req.getMerchantIdSet())
                .eq(null != req.getStatus(), Merchant::getStatus, req.getStatus())
        ).stream()
                .map(MerchantVO::new).collect(Collectors.toList());
    }
}
